// ==UserScript== // @name 🥇优学院小助手(2023/03/09更新)|视频-章节测试-作业考试查题(三合一)|自动挂机|答题收录|用过都说好 // @namespace http://tampermonkey.net/ // @version 1.2.4 // @description 优学院小助手,用于课件视频+课后作业+考试界面辅助答题(自动答题)。 // @author Miss. // @match https://utest.ulearning.cn/* // @match https://*.ulearning.cn/*/homework.do* // @match https://ua.ulearning.cn/learnCourse/learnCourse.html?* // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js // @grant unsafeWindow // @grant GM_setClipboard // @grant GM_xmlhttpRequest // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @connect 106.75.227.24 // @antifeature ads // @antifeature payment // ==/UserScript== (function () { "use strict"; //属性 注单用户限制搜索次数 const $w = unsafeWindow; const set = { get_answer: "http://106.75.227.24:8877/fuck/cha.php", upload_data: "http://106.75.227.24:8877/fuck/upload.php", heartbeat: "http://106.75.227.24:8877/fuck/server.php", Dealagging: false, left: 0, top: 0, //下方双引号内填写对应token保存 例如:token: "XIqflbdhUSYskJaG" 已抛弃 token: "", timestamp: -1, }; //处理类 class Deal { constructor() { this.text = ""; this.data = []; } append(k, v) { this.data.push(encodeURIComponent(k) + "=" + encodeURIComponent(v)); this.text = this.data.join("&").replace(/%20/g, "+"); } } //工具包 const Util = { post_form: function (url, data, onload, onerror) { Util.post(url, data, onload, onerror, { "Content-Type": "application/x-www-form-urlencoded" }); }, post: function (url, data, onload, onerror, headers) { let data_form = new Deal(); for (let value in data) { data_form.append(value, data[value]); } GM_xmlhttpRequest({ method: "POST", url: url, headers: headers, data: data_form.text, onload: onload, onerror: onerror, }); }, get: function (url, data, onload, onerror) { let data_form = new Deal(); for (let value in data) { data_form.append(value, data[value]); } GM_xmlhttpRequest({ method: "GET", url: url + "?" + data_form.text, onload: onload, onerror: onerror, }); }, upload_api: function (data, send) { if (set.token == -1) { setTimeout(Util.upload_api, 1000, data, true); if (send === true) { return; } } Util.post_form(set.upload_data, { token: "" + set.token, data: JSON.stringify(data), }); }, upload_paper: function (paper, pid, eid) { Util.upload_api({ op: 4,eid: eid, pid: pid, paper: paper }); }, upload_answer: function (answer, pid, eid) { Util.upload_api({ op: 5,eid: eid, pid: pid, answer: answer }); }, upload_title: function (title, quetype, quetxt) { Util.upload_api({ op: 6, type: quetype, title: title ,cont: quetxt }); }, get_answer: function (question, quetype, td,$ans) { return new Promise((resolve, reject) => { let data_form = new Deal(); let datas = { question: question,type: quetype }; for (let value in datas) { data_form.append(value, datas[value]); } GM_xmlhttpRequest({ method: "GET", url: set.get_answer + "?" + data_form.text + "&token=" + set.token, onload: function (r) { if (r.status == 200) { try { let data = JSON.parse(r.responseText); if (data.code == 1) { td.innerText = data.data[0].answer; td.addEventListener("click", function () { GM_setClipboard(data.data[0].answer); }); if($ans) respondentExam._answer(data.data[0].answer,$ans); return ; } else if (data.code == 0) { td.innerText = "无答案(已回传服务器)"; return 0; } } catch (e) {console.log("error")} } // td.innerText = "服务器错误,请加群反馈"; resolve(r); }, onerror: function (e) { td.innerText = "服务器错误,请加群反馈"; resolve(e); } }); }) }, }; // 优学院 const youxueyuan = { $startBtn: null, // 开始按钮 $stopBtn: null, // 暂停按钮 $rateText: null, //倍速 timer: null, // 定时器 // 初始化 init() { this.$startBtn = $(''); this.$stopBtn = $(''); this.$rateText = $('倍速:'); let $erviceMask = $(''); $('#get_answer').parent().parent().parent().append($erviceMask); $erviceMask.append(this.$startBtn).append(this.$stopBtn).append(this.$rateText); $('#hide_show').click(); $('#get_answer').hide(); $('#hide_show').hide(); this.$stopBtn.hide(); this.bindEvent(); }, // 绑定事件 bindEvent() { this.$startBtn.click(() => { this.logic(); this.timer = setInterval(() => { this.logic() }, 1500); this.$startBtn.hide(); this.$stopBtn.show(); }); this.$stopBtn.click(() => { clearInterval(this.timer); this.$stopBtn.hide(); this.$startBtn.show(); // 暂停视频播放 if ($(".file-media").length > 0) { let $allVideos = $(".file-media"); for (let i = 0; i < $allVideos.length; i++) { if ($('.mejs__button.mejs__playpause-button button').eq(i).attr('title') == '暂停') { $('.mejs__button.mejs__playpause-button button')[i].click(); $('.mejs__button.mejs__volume-button button')[i].click(); } } } }) }, // 视频主逻辑 logic() { // 如果页面中弹出了框框 if ($('.modal.fade.in').length > 0) { switch ($('.modal.fade.in').attr('id')) { case 'statModal': { $("#statModal .btn-hollow").eq(-1).click(); break; } case 'alertModal': { if ($("#alertModal .btn-hollow").length > 0) { $("#alertModal .btn-hollow").eq(-1).click(); } else { $("#alertModal .btn-submit").click(); } break; } } return; } // 如果页面中有视频 if ($(".file-media").length > 0) { let $allVideos = $(".file-media"); let i = 0; for (; i < $allVideos.length; i++) { // 这个视频还没有看完并且不是播放状态 if (!$("[data-bind='text: $root.i18nMessageText().finished']").get(i)) { let _rate = document.getElementById("rate").value; // 视频不是播放状态 if ($('.mejs__button.mejs__playpause-button button').eq(i).attr('title') == '播放') { $(".mejs__speed-selector-input")[i * 4].value = parseFloat(_rate); $(".mejs__speed-selector-input")[i * 4].click(); $('.mejs__button.mejs__speed-button button')[i].innerText = _rate+'x'; $('.mejs__button.mejs__playpause-button button')[i].click(); $('.mejs__button.mejs__volume-button button')[i].click(); } break; } } if (i == $allVideos.length) { $('.next-page-btn.cursor').click(); } return; } // 如果是做题界面 if ($('.question-setting-panel').length > 0) { // 修正当前状态 let $submitBtn = $('.question-operation-area button').eq(0); if ($submitBtn.text() == '重做') { $submitBtn.click(); return; } // 获取当前页面 ID let parentId = $('.page-name.active').parent().attr('id').substring(4); // 开始同步答题 let $questions = $('.question-element-node'); for (let i = 0; i < $questions.length; i++) { respondent._answer(parentId, $questions.eq(i)); } // 提交答案 $submitBtn.click(); setTimeout(() => { $('.next-page-btn.cursor').click(); }, 300); sleep return; } // 下一页 $('.next-page-btn.cursor').click(); }, } // 答题器 const respondent = { parentId: null, // 页面ID questionId: null, // 当前解答问题的ID $questionNode: null, // 当前解答问题的根节点 // 回答问题 // @param parentId 页面ID // @param questionNode 问题根节点 _answer(parentId, $questionNode, callback) { this.parentId = parentId; this.$questionNode = $questionNode; this.questionId = this.$questionNode.find('.question-wrapper').attr('id').substring(8); let questionType = $questionNode.find('.question-type-tag').text().trim(); switch (questionType) { case '多选题': { this._answerMultiSelect(); break; } case 'Multiple Choice': case '单选题': { this._answerSelect(); break; } case 'True/False': case '判断题': { this._answerJudge(); break; } case 'Fill in the Blank': case '填空题': { this._answerInput(); break; } case 'Short Answer': case '简答题': { this._answerSimpleQuestion(); break; } case 'Word Bank': case '选词填空': { this._answerChoicesQuestion(); break } case 'Sequence': case '排序题': { this._answerRankQuestion(); break } case '综合题': { console.log("error") break; } } if (callback && typeof callback == 'function') callback(); }, // 解答多选题 _answerMultiSelect() { // 多选题需要清空当前答案 let $selected = this.$questionNode.find('.checkbox.selected'); for (let i = 0; i < $selected.length; i++) { $selected.eq(i).click(); } // 获取答案并选择 let $emptySelected = this.$questionNode.find('.checkbox'); let answerArray = this._syncGetAnswer().correctAnswerList; for (let i = 0; i < answerArray.length; i++) { let index = answerArray[i].charCodeAt() - 'A'.charCodeAt(); $emptySelected.eq(index).click(); } }, // 解答单选题 _answerSelect() { let $emptySelected = this.$questionNode.find('.checkbox'); let answerArray = this._syncGetAnswer().correctAnswerList; for (let i = 0; i < answerArray.length; i++) { let index = answerArray[i].charCodeAt() - 'A'.charCodeAt(); $emptySelected.eq(index).click(); } }, // 解答判断题 _answerJudge() { let questionAnswer = this._syncGetAnswer().correctAnswerList[0]; if (questionAnswer=="true") { this.$questionNode.find('.choice-btn.right-btn').click(); } else { this.$questionNode.find('.choice-btn.wrong-btn').click(); } }, // 解答填空题 _answerInput() { let $emptyInput = this.$questionNode.find('.blank-input'); let inputAnswers = this._syncGetAnswer().correctAnswerList; for (let i = 0; i < inputAnswers.length; i++) { $emptyInput.eq(i).val(inputAnswers[i]); } }, // 解答简答题 _answerSimpleQuestion() { let $emptyInput = this.$questionNode.find('.form-control'); let inputAnswers = this._syncGetAnswer().correctAnswerList; for (let i = 0; i < inputAnswers.length; i++) { let answerText = re_text(inputAnswers[i].replace(/【答案要点】/g, '')); $emptyInput.eq(i).val(answerText); $emptyInput.change(); } }, //选词填空题 _answerChoicesQuestion(){ let $emptyInput = this.$questionNode.find('.cloze-input'); let inputAnswers = this._syncGetAnswer().subQuestionAnswerDTOList; console.log(inputAnswers) for (let i = 0; i < inputAnswers.length; i++) { let answerText = inputAnswers[i].correctAnswerList[0]; $emptyInput.eq(i).val(answerText); $emptyInput.change(); } }, //排序题 _answerRankQuestion(){ let $emptyInput = this.$questionNode.find('.answer-blank'); let inputAnswers = this._syncGetAnswer().correctAnswerList; for (let i = 0; i < inputAnswers.length; i++) { let answerText = inputAnswers[i]; $emptyInput.eq(i).html(answerText); $emptyInput.change(); } }, // 同步获取测试答案 _syncGetAnswer() { let res_answer; $.ajaxSettings.async = false; $.get('https://api.ulearning.cn/questionAnswer/' + this.questionId + '?parentId=' + this.parentId,function(xhr){res_answer = xhr;}) $.ajaxSettings.async = true; return res_answer; } }; // 考试答题器 const respondentExam = { answerText : null, $questionNode: null, // 当前解答问题的根节点 // 回答问题 // @param answerText 传来答案 // @param questionNode 问题根节点 _answer(answerText,$questionNode, callback) { this.answerText = answerText; this.$questionNode = $questionNode; let questionType = $questionNode.find('.base-question .title .tip').text().match(/\d+\.(.*?)\s+/)[1]; switch (questionType) { case '多选题': { this._answerMultiSelect(); break; } case '单选题': { this._answerSelect(); break; } case '判断题': { this._answerJudge(); break; } case '填空题': { this._answerInput(); break; } case '简答题': { this._answerSimpleQuestion(); break; } }if (callback && typeof callback == 'function') callback(); }, // 解答多选题 _answerMultiSelect() { // 根据答案匹配 let $emptySelected = this.$questionNode.find('.choice-list label .rich-text'); let answerArray = this.answerText; for (let i = 0; i < $emptySelected.length; i++) { (function(j) { setTimeout( function timer() { if(answerArray.indexOf(re_text($emptySelected.eq(j).text())) != -1) $emptySelected.eq(j).click(); }, j*1000 ); })(i); } }, // 解答单选题 _answerSelect() { let $emptySelected = this.$questionNode.find('.choice-list label .rich-text'); let answerArray = this.answerText; for (let i = 0; i < $emptySelected.length; i++) { if(similar($emptySelected.eq(i).text(),answerArray)>60) $emptySelected.eq(i).click(); } }, // 解答判断题 _answerJudge() { let questionAnswer = this.answerText; if (questionAnswer=="true") { this.$questionNode.find('.ul-radio__input').eq(0).click(); } else { this.$questionNode.find('.ul-radio__input').eq(1).click(); } }, // 解答填空题 _answerInput() { let answerArray = this.answerText.replace(/\s*/g,"").split('||'); for (let i = 0; i < answerArray.length; i++) { // 首先获取input元素 let num_input = document.querySelectorAll('.blank-question input')[i]; // 给input元素赋值 num_input.value = answerArray[i]; // 创造事件 var event = document.createEvent('HTMLEvents'); event.initEvent("input", true, true); event.eventType = 'message'; // 调度事件 num_input.dispatchEvent(event); } }, // // 解答简答题 // _answerSimpleQuestion() { // } // }, } //cdn库 https://www.bootcdn.cn/layui/ $('head').append(''); $.getScript("https://lib.baomitu.com/layui/2.6.8/layui.js", function(data, status, jqxhr) { layui.use('element', function(){ var element = layui.element; }); layer.closeAll(); Re_Write(); Init(); Set_Heart(); window.onhashchange = function() { layer.closeAll(); Re_Write(); Init(); Set_Heart(); }; }); //拦截 function Re_Write() { const open = unsafeWindow.XMLHttpRequest.prototype.open; unsafeWindow.XMLHttpRequest.prototype.open = function () { let url = arguments[1]; if (url) { if (url.match(/getPaperForStudent/) && url.match(/examId=(\d+)/) && url.match(/paperId=(\d+)/)) { let examID = url.match(/examId=(\d+)/)[1]; let paperID = url.match(/paperId=(\d+)/)[1]; this.addEventListener('load', () => { let data = JSON.parse(this.responseText); Util.upload_paper(data, paperID, examID); }); } else if (url.match(/getCorrectAnswer/) && url.match(/examId=(\d+)/) && url.match(/paperId=(\d+)/)) { let examID = url.match(/examId=(\d+)/)[1]; let paperID = url.match(/paperId=(\d+)/)[1]; this.addEventListener('load', () => { let data = JSON.parse(this.responseText); Util.upload_answer(data, paperID, examID); }); } } return open.apply(this, arguments); }; } //UI初始化 function Init() { if (!document.body) { setTimeout(Init, 100); return; } let style = document.createElement("style"); style.innerHTML = ` #answer_key { min-height: 22px; max-height: 250px; overflow: auto; } .td_center { text-align: center; } .td_left { text-align: left; } .td_right { text-align: right; } .td_width { width: 125px; } img { pointer-events: none; width: 260px; }`; let div = document.createElement("div"); let pageurl = window.location.href.split("?")[0]; if(pageurl=="https://utest.ulearning.cn/"){ div.setAttribute("style", "background-color: #C6DFF7; position: fixed; top: 54px; right: 300px; width: 270px; opacity: 0.75; border-style: dotted; border-width: 3px;z-index:99999;"); } else{ div.setAttribute("style", "background-color: #C6DFF7; position: fixed; top: 54px; left: 50px; width: 270px; opacity: 0.75; border-style: dotted; border-width: 3px;z-index:99999;"); } div.innerHTML = `

Ulearning 小助手

服务器状态: 获取中..
题目 答案
`; document.body.appendChild(style); document.body.appendChild(div); Bind(); div.addEventListener("mousedown", function (e) { set.Dealagging = true; let mer = div.getBoundingClientRect(); set.left = e.clientX - mer.left; set.top = e.clientY - mer.top; }); div.addEventListener("mouseup", function () { set.Dealagging = false; }); div.addEventListener("mousemove", function (e) { if (set.Dealagging) { let x = e.clientX - set.left; let y = e.clientY - set.top; div.style.left = x + "px"; div.style.top = y + "px"; } }); let new_uri= window.location.href.split("?")[0]; if(new_uri=="https://ua.ulearning.cn/learnCourse/learnCourse.html"){ youxueyuan.init(); } else{ set.token == "" ? Judge():Heart(); } } //token function getToken(info){ return new Promise(function(success,fail){ $w.layer.prompt({ title: info, formType: 0, btn:['确认','不用','获取卡密'], btn2: function(index){ $w.layer.close(index); GM_setValue('yToken',false); success(); }, btn3:function(){ GM_openInTab("http://2uu.fun",{ active: true, setParent :true}); return false; }, cancel: function(index){ GM_setValue('yToken',false); success(); } },function(pass, index){ $w.layer.close(index); GM_setValue('yToken',pass); set.token = pass; Heart().then(([value,ttimes]) => { if(!value){ getToken("填写token有误 请仔细检查") } if(ttimes >0 && ttimes <= 20){ getToken("次数即将用尽 是否需要填写新的token") } }) success(); }); }) } //隐藏 function Bind() { let get_answer = document.querySelector("#get_answer"); get_answer && (function () { get_answer.addEventListener("click", Get_Answer, false); })(); let hide_show = document.querySelector("#hide_show"); hide_show && (function () { hide_show.addEventListener("click", function () { let answer_key = document.querySelector("#answer_key"); answer_key && (function () { answer_key.getAttribute("style") === "display: block;" && (function () { answer_key.setAttribute("style", "display: none;"); return true; })() || (function () { answer_key.setAttribute("style", "display: block;"); })(); })(); }, false); })(); } function Set_Heart() { // Heart(); setInterval(Heart, 15000); } //服务器状态 function Heart() { return new Promise((resolve, reject) => { let server_status = document.querySelector("#server_status"); if (server_status) { set.timestamp = new Date().getTime(); Util.get(set.heartbeat, { token: "" + set.token, timestamp: "" + set.timestamp }, function (xhr) { try { let xhr_json = JSON.parse(xhr.responseText); if (xhr_json.data.status) { server_status.innerText = "正常[查询剩余:"+xhr_json.data.times+"]"; resolve([xhr_json.data.status,xhr_json.data.times]); } else{ server_status.innerText = "正常[Token未知]"; resolve([xhr_json.data.status,0]); } } catch (e) {server_status.innerText = "异常";} }, function () { server_status.innerText = "异常"; }); } }) } //判断ip状态 function Judge() { let server_status = document.querySelector("#server_status"); if (server_status && (set.token=="")) { set.timestamp = new Date().getTime(); Util.get("http://106.75.227.24:8877/fuck/judge.php", {}, function (xhr) { try { let xhr_json = JSON.parse(xhr.responseText); if (xhr_json.code == 0) { server_status.innerText = "异常[本机IP不可用]"; // $w.layer.alert('IP查询已上限,请您获取Token使用'); getToken(xhr_json.info); } else{ server_status.innerText = "正常[每日免费次数]"; getToken("目前免费次数 稳定可选择填写token"); } } catch (e) {server_status.innerText = "异常"} }, function () { server_status.innerText = "异常"; }); } } function Clear_Table() { let answer_table = document.querySelector("#answer_table"); answer_table && (function () { while (answer_table.rows.length > 1) { answer_table.deleteRow(1); } })(); } //题库 function Get_Answer() { Clear_Table(); let question_area = document.querySelectorAll(".question-area"); question_area && (function(){ question_area.forEach(function (item) { item.childNodes.forEach(function (div) { if (div.className.indexOf("next-part") != -1) { return; } switch (div.className) { case "question-item": way1(div); break; default: way2(div); } }); }); })(); let question_wrap = document.querySelectorAll("#questionWrap"); question_area && (function(){ question_wrap.forEach(function (item) { item.childNodes.forEach(function (div){ switch (div.className) { case "multiple-choices": case "judge": case "fill": case "match": case "sort": way3(div); break; case "blankFill": case "cloze": default: way2(div); } }); }); })(); Heart(); } //作业 function way3(div) { let index = div.querySelector(".position-rltv").firstChild.innerText; let title = div.querySelector(".position-rltv").lastChild; let quetype = div.firstChild.dataset.type; let title_text = title && title.innerText || ""; let answer_table = document.querySelector("#answer_table"); answer_table && (async function () { let tr = answer_table.insertRow(); let t = tr.insertCell(); t.innerText = "【" + index.split(".")[0] + "】" + title_text; t.addEventListener("click", function () { GM_setClipboard(this.innerText); }, false); t = tr.insertCell(); await Util.get_answer(title_text, quetype, t); })(); } function way2(div) { // 英语答题类 待提供测试账号开发 } //考试 function way1(div) { let qid = div.firstChild.__vue__.question.questionid; if (!qid) { return; } let index = div.firstChild.__vue__.question.index; let title = re_text(div.firstChild.__vue__.question.title); let quetype = div.firstChild.__vue__.question.type; let quetxt = ""; let cho = div.firstChild.__vue__.question.choices; if(quetype==1||quetype==2){ cho.forEach(function(item){quetxt+=item.text+"||";}) quetxt = re_text(quetxt); } let answer_table = document.querySelector("#answer_table"); answer_table && (async function () { let tr = answer_table.insertRow(); let t = tr.insertCell(); t.innerText = "【" + index + "】" + title; t.addEventListener("click", function () { GM_setClipboard(this.innerText); }, false); t = tr.insertCell(); let codeAnswer = await Util.get_answer(title, quetype, t,$(div)); if(codeAnswer==0){ //无答案回传 Util.upload_title(title, quetype, quetxt); } })(); } //相似度匹配 function similar(s, t, f) { if (!s || !t) { return 0 } if (s === t) { return 100; } var l = s.length > t.length ? s.length : t.length; var n = s.length; var m = t.length; var d = []; f = f || 2; var min = function (a, b, c) { return a < b ? (a < c ? a : c) : (b < c ? b : c) }; var i, j, si, tj, cost; if (n === 0) return m if (m === 0) return n for (i = 0; i <= n; i++) { d[i] = []; d[i][0] = i; } for (j = 0; j <= m; j++) { d[0][j] = j; } for (i = 1; i <= n; i++) { si = s.charAt(i - 1); for (j = 1; j <= m; j++) { tj = t.charAt(j - 1); if (si === tj) { cost = 0; } else { cost = 1; } d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); } } let res = (1 - d[n][m] / l) * 100; return res.toFixed(f) } //正则处理 function re_text(text) { text = text.replace(/<\/?.+?\/?>/g,''); text = text.replace(/\t/g, ""); text = text.replace(/\n/g, ""); text = text.replace(/\r/g, ""); text = text.replace(/&.*?;/g, ""); return $.trim(text.substr(0,text.length)); } //未启用 function sleep(d){ for(var t = Date.now();Date.now() - t <= d;); } })();